package cron

import (
	bufio2 "bufio"
	"fmt"
	"os"
	"time"
)

// NewCron 对外新建一个定时任务，f是执行闭包，inter是f的入参
func NewCron(tConfig TimeConfig, ctx *Context, f ...DoCronFunc) *JobCron {
	j := new(JobCron)

	j.doCron = make(chan struct{})
	j.BeginStopChan = make(chan struct{})
	j.QuitChan = make(chan struct{})

	j.tConfig = tConfig
	j.Task = f
	j.ctx = ctx
	fmt.Println(*j)
	return j
}

func (j *JobCron) Start() {
	j.tConfig.BeginAt = time.Now()
	go j.reCronIt()
	for _, timePass := range j.tConfig.Interval {
		ticker := time.NewTicker(timePass)
		go func() {
			for {
				select {
				case <-ticker.C:
					fmt.Println("zhushe?")
					for _, task := range j.Task {
						task(j.ctx)
					}
				}
			}
		}()
	}
	go func() {
		for {
			select {
			//bs(begin and stop)向通道发送数据，第一次为暂停，实现让协程的假挂起，第二次为重新运行
			case <-j.BeginStopChan:
				fmt.Println("if stop")
				func() {
					select {
					case <-j.BeginStopChan:
						//把管道清空
						<-j.doCron
						return
					}
				}()
			case <-j.doCron:
				for _, task := range j.Task {
					task(j.ctx)
				}
			}
		}
	}()
	go func() {
		for {
			buf := bufio2.NewReader(os.Stdin)
			line, _, err := buf.ReadLine()
			if err != nil {
				panic(err)
			}
			if string(line) == "stop" {
				j.BeginStopChan <- struct{}{}
			}
			if string(line) == "quit" {
				j.QuitChan <- struct{}{}
			}
		}
	}()
	for {
		select {
		case <-j.QuitChan:
			return
		}
	}
}

func (j *JobCron) TimeEcho(F func(mouth, week, day, hour, minute, second uint) bool) {
	ticker := time.NewTicker(time.Second)

	for {
		select {
		case <-ticker.C:
			mo := uint(time.Now().Month())
			w := uint(time.Now().Weekday())
			d := uint(time.Now().Day())
			h := uint(time.Now().Hour())
			m := uint(time.Now().Minute())
			s := uint(time.Now().Second())
			re := F(mo, w, d, h, m, s)
			if re {
				j.doCron <- struct{}{}
			}
		}
	}

}

// reCronIt 对定时执行设定一个chan

func (j *JobCron) reCronIt() {
	iTime := j.tConfig.Cron.toITime()
	j.TimeEcho(func(mouth, week, day, hour, minute, second uint) bool {
		nowTimeSlice := make([]uint, 6)
		nowTimeSlice[0] = mouth
		nowTimeSlice[1] = week
		nowTimeSlice[2] = day
		nowTimeSlice[3] = hour
		nowTimeSlice[4] = minute
		nowTimeSlice[5] = second
		//数有几个满足
		count := 0
		for i, val := range iTime {
			if len(val) == 0 {
				count++
				continue
			}
			if ifVin(nowTimeSlice[i], val) {
				count++
			}
		}
		if count == 6 {
			return true
		}
		return false
	})
}

// 判断一个值是否在切片里面
func ifVin(i uint, slice []uint) bool {
	for _, val := range slice {
		if i == val {
			return true
		}
	}
	return false
}
